<?php
/**
 * 订单类.
 * User: chan
 * Date: 2017/9/28 19:24
 */

namespace app\api\logic;
use app\api\BaseModel;
use think\Db;
use think\Exception;
use think\Log;

class Order extends BaseModel
{
    protected $orderProducts;
    protected $products;
    protected $uid;
    protected $voucher;

    public function place()
    {
        $res = $this->checkData(
            ["address_id","type"],
            ["收货地址不能为空","订单类型不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $type = intval($this->requestData['type']);
        if(!in_array($type,[1,2])) return array('message' => '订单类型错误');
        try{

            switch($type){
                case 1://商品
                    if(!array_key_exists('spec_id',$this->requestData)) return array('message' => '商品规格不能为空');
                    if(!array_key_exists('count',$this->requestData)) return array('message' => '商品数量不能为空');
                    $this->requestData['products'][] = array(
                        'spec_id' => intval($this->requestData['spec_id']),
                        'count' => intval($this->requestData['count']),
                    );
                    break;
                case 2://购物车
                    $this->requestData['products'] = $this->getCartProducts();
                    break;
            }

            $this->products = $this->getProductsByOrder($this->requestData['products']);
            $this->getOrderStatus();

            //验证卡券信息
            if(array_key_exists('voucher_id',$this->requestData)){
                $this->voucher($this->requestData['voucher_id']);
            }

            $orderSnap = $this->snapOrder();
            $result = self::createOrder($orderSnap);

        }catch (\Exception $e){
            return array('message' => $e->getMessage());
        }

        return $result;
    }
    /**
     * 根据订单查询产品
     */
    private function getProductsByOrder($orderProducts)
    {
        $productIds = array_column($orderProducts,'spec_id');
        $products = db('goods')->alias('g')
            ->join('goods_option_value gov','gov.goodsid = g.id')
            ->field('gov.id as spec_id,g.name,g.image,g.status,gov.price,gov.stock,gov.spec_name,g.id as goods_id,g.postage')
            ->where(['gov.id' => array('in',$productIds)])
            ->select();
        return $products;
    }

    private function voucher($voucher_id){
        $this->voucher = db('myvoucher')->where(['user_id' => $this->user['uid'],'voucher_id' => $voucher_id])->find();
        if(!$this->voucher) throw new \Exception('找不到优惠劵');
        //判断是否满足优惠劵使用条件
        if($this->orderProducts['productTotalPrice'] < $this->voucher['fullmoney']){
            throw new \Exception('该优惠劵不满足使用条件');
        }
    }

    /**
     * 获取订单状态
     *
     */
    private function getOrderStatus()
    {
        $this->orderProducts = array(
            'products' => array(),
            'productTotalPrice' => 0,
            'totalCount' => 0,
            'postage' => 0,
        );

        foreach ($this->requestData['products'] as $orderProduct) {
            $this->getProductStatus(
                $orderProduct['spec_id'],
                $orderProduct['count'],
                $this->products
            );
        }

    }



    private function getProductStatus($productId, $oCount, $products)
    {
        $key = array_search($productId,array_column($products,'spec_id'));
        if($key !== false){
            if($products[$key]['status'] != 1) throw new \Exception('订单创建失败,'.$products[$key]['name'].'商品已下架');
            if($oCount < 1) throw new \Exception('订单创建失败,'.$products[$key]['name'].'商品'.$products[$key]['spec_name'].'规格购买数量不能少于1件');
            if($oCount > $products[$key]['stock']) throw new \Exception('订单创建失败,'.$products[$key]['name'].'商品'.$products[$key]['spec_name'].'规格库存不足');
        }else{
            throw new \Exception('规格id为' . $productId . '的商品不存在');
        }

        $product = $products[$key];
        $productStatus['product_id'] = $product['goods_id'];
        $productStatus['product_name'] = $product['name'];
        $productStatus['product_img'] = $product['image'];
        $productStatus['spec'] = $product['spec_name'];
        $productStatus['count'] = $oCount;
        $productStatus['product_price'] = $product['price'];
        $productStatus['create_time'] = TIMESTAMP;
        $this->orderProducts['products'][] = $productStatus;
        $this->orderProducts['productTotalPrice'] += $product['price'] * $oCount;
        $this->orderProducts['totalCount'] += $oCount;


        //取商品邮费最大值
        if($this->orderProducts['postage'] < $product['postage']){
            $this->orderProducts['postage'] = $product['postage'];
        }
    }


    private function getUserAddress()
    {
        $userAddress = db('user_address')->where(['user_id' => $this->user['uid'],'address_id' => $this->requestData['address_id']])
            ->find();
        if (!$userAddress) {
            throw new \Exception(['message' => '用户收货地址不存在，下单失败']);
        }
        return $userAddress;
    }

    private function createOrder($snap)
    {
        Db::startTrans();
        try {
            $order = db('order');
            $orderID = $order->insertGetId($snap);

            foreach ($this->orderProducts["products"] as &$pointer) {
                $pointer['order_id'] = $orderID;
            }

            $orderProduct = db('order_product');
            $orderProduct->insertAll($this->orderProducts['products']);

            //减少库存
            $m_goods_option_value = db('goods_option_value');
            foreach($this->orderProducts['products'] as $g){
                $m_goods_option_value->where(['goodsid' => $g['product_id'],'spec_name' => $g['spec']])->setDec('stock',$g['count']);
            }

            //更新优惠劵状态
            if($snap['voucher_id'] > 0){
                db('myvoucher')->where(['id' => $snap['voucher_id']])->update(['status' => 1]);
            }

            //从购物车入口则清空选中的商品
            if($this->requestData['type'] == 2){
                db('cart')->where(['uid' => $this->user['uid'],'isselect' => 1])->delete();
            }


            $pay_info = array(
                'pay_sn' => 'P'.$this->generateOrderNo(),
                'money' => $snap['paid_price'],
                'memid' => $snap['user_id'],
                'create_time' => $snap['create_time'],
                'mem_name' => $this->user['nickname'],
                'record_id' => $orderID
            );

            db('pay_log')->insert($pay_info);

            Db::commit();
        } catch (Exception $ex) {
            Db::rollback();
            throw new \Exception($ex->getMessage());
        }

        return array(
            'pay_sn' => $pay_info['pay_sn'],
            'money' => $pay_info['money'],
            'create_time' => $pay_info['create_time'],
        );
    }

    // 预检测并生成订单快照
    private function snapOrder()
    {
        $snap = [
            'order_sn' => $this->generateOrderNo(),
            'total_price' => $this->orderProducts['productTotalPrice'],
            'total_count' => $this->orderProducts['totalCount'],
            'product_name' => $this->products[0]['name'],
            'product_img' => $this->products[0]['image'],
            'user_id' => $this->user['uid'],
            'address' => json_encode($this->getUserAddress()),
            'voucher_id' => !empty($this->voucher) ? $this->voucher['id'] : 0,
            'voucher_deduction' => !empty($this->voucher) ? $this->voucher['money'] : 0,
            'create_time' => TIMESTAMP,
            'postage' => $this->orderProducts['postage'],
            'paid_price' => $this->orderProducts['productTotalPrice'] + $this->orderProducts['postage'],
            'remarks' => array_key_exists('remarks',$this->requestData) ? htmlspecialchars($this->requestData['remarks']) : '',
        ];

        if($snap['voucher_id'] > 0){
            $snap['paid_price'] -= $snap['voucher_deduction'];
        }

        if (count($this->products) > 1) {
            $snap['product_name'] .= '等';
        }

        return $snap;
    }


    public static function generateOrderNo()
    {
        $yearCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn =
            $yearCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 999));
        return $orderSn;
    }

    /**
     * 获取购物车商品
     */
    private function getCartProducts(){
        $cart = db('cart')->field('specid as spec_id,total as count')->where(['uid' => $this->user['uid'],'isselect' => 1])->select();
        if(empty($cart)) throw new \Exception('您的购物车没有选中的商品');
        return $cart;
    }

    /**
     * 预订单
     */
    public function preOrder(){
        if(!array_key_exists('type',$this->requestData)) return array('message' => '订单类型不能为空');
        try{

            switch(intval($this->requestData['type'])){
                case 1://商品
                    if(!array_key_exists('spec_id',$this->requestData)) return array('message' => '商品规格不能为空');
                    if(!array_key_exists('count',$this->requestData)) return array('message' => '商品数量不能为空');
                    $this->requestData['products'][] = array(
                        'spec_id' => intval($this->requestData['spec_id']),
                        'count' => intval($this->requestData['count']),
                    );
                    break;
                case 2://购物车
                    $this->requestData['products'] = $this->getCartProducts();
                    break;
                default:
                    throw new \Exception('订单类型错误');
            }

            $this->products = $this->getProductsByOrder($this->requestData['products']);
            $this->getOrderStatus();

        }catch (\Exception $e){
            return array('message' => $e->getMessage());
        }

        $data = $this->orderProducts;
        $data['address'] = db('user_address')->where(['user_id' => $this->user['uid'],'isdefault' => 1])->find();
        $data['voucher'] = db('myvoucher')->where([
            'user_id' => $this->user['uid'],
            'fullmoney' => array('lt',$this->orderProducts['productTotalPrice']),
            'status' => 0,
            'start_time' => array('lt',TIMESTAMP),
            'end_time' => array('gt',TIMESTAMP)
        ])->select();
        foreach($data['products'] as &$g){
            $g['product_img'] = __ROOT__ . '/static/uploads'.str_replace('\\',"/",$g['product_img']);
            $g['create_time'] = date('Y-m-d h:i:s',$g['create_time']);
        }

        return $data;

    }


    public function getOrderGoods($order_id){
        $order = db('order')->where(['order_id' => $order_id,'user_id' => $this->user['uid']])->find();
        if(!$order) throw new \Exception('找不到相关订单');
        $order_goods = db('order_product')->alias('og')
            ->join('goods g','g.id = og.product_id')
            ->join('goods_option_value gov','gov.goodsid = og.product_id and gov.spec_name = og.spec')
            ->field('gov.id as spec_id,og.count,gov.stock')
            ->where(['og.order_id' => $order_id,'g.status' => 1,'gov.stock' => ['gt',0]])
            ->select();
        if(empty($order_goods)) throw new \Exception('找不到商品,商品可能卖完或下架');
        $data = array();
        foreach ($order_goods as $og){
            if($og['stock'] >= $og['count']){
                $data[] = array(
                    'spec_id' => $og['spec_id'],
                    'count' => $og['count'],
                );
            }
        }
        if(empty($data)) throw new \Exception('找不到商品,商品可能卖完或下架');
        return $data;
    }

    /**
     * 订单列表
     */
    public function index(){
        if(array_key_exists('page',$this->requestData)){
            $page = intval($this->requestData['page']) > 0 ? intval($this->requestData['page']) : 1;
        }else{
            $page = 1;
        }
        if(array_key_exists('limit',$this->requestData)){
            $limit = intval($this->requestData['limit']) > 0 ? intval($this->requestData['limit']) : 10;
        }else{
            $limit = 10;
        }
        $where = array();
        if (array_key_exists('type', $this->requestData)) {
            $type = intval($this->requestData['type']);
            switch ($type){
                case 1://待收货
                    $where['order_state'] = 2;
                    break;
                case 2://已完成
                    $where['order_state'] = 3;
                    break;
                case 3://已取消
                    $where['order_state'] = -1;
                    break;
                case 4://待付款
                    $where['order_state'] = 0;
                    break;
                default:
                    return array('message' => '订单类型错误');
            }
        }

        $where['delete'] = '0';
        $where['user_id'] = $this->user['uid'];
        $m_order = db('order');

        if(isset($type)){
            if($type != ORDER_STATUS_FAILURE){
                $count = $m_order->where($where)->count();
            }else{
                $count = $m_order->alias('mo')
                        ->join('refund rf','rf.order_id = mo.order_id')
                        ->count();
            }
        }else{
            $count = $m_order->where($where)->count();
        }

        if($count > 0){
            $list = $m_order->where($where)
                ->field('order_id,order_sn,order_state,total_count,paid_price,refund_id,iscomment,create_time')
                ->order('create_time desc')
                ->page($page,$limit)
                ->select();
            
            $m_order_product = db('order_product');
            $m_refund = db('refund');
            foreach($list as $key=>&$l){
                $l['goods'] = $m_order_product->where(['order_id' => $l['order_id']])->select();
                
                foreach($l['goods'] as &$lg){
                    if(!empty($lg['product_img'])){
                        $lg['product_img'] = __ROOT__ . '/static/uploads'.str_replace('\\',"/",$lg['product_img']);
                    }
                    $lg['create_time'] = date('Y-m-d',$lg['create_time']);
                }
                $l['refund'] = null;
                if($l['refund_id'] > 0){
                    $l['refund'] = $m_refund->field('refund_id,status,money,refund_sn')->where(['refund_id' => $l['refund_id'],'order_id' => $l['order_id']])->find();
                    /*$l['refund']['images'] = json_decode($l['refund']['images']);
                    foreach($l['refund']['images'] as &$fg){
                        $fg = __ROOT__ . '/static/uploads/'.str_replace('\\',"/",$fg);
                    }
                    if(!empty($l['refund']['reason'])){
                        $l['refund']['reason'] = htmlspecialchars_decode($l['refund']['reason']);
                    }*/
                }
				
				//查询支付单号
                /*$pay_sn = db('pay_log')->where(['record_id'=>$l['order_id']])->field('pay_sn')->find();
	
                if(!empty($pay_sn)){
                    $list[$key]['pay_sn'] = $pay_sn['pay_sn'];
                }else{
                    $list[$key]['pay_sn'] = '';
                }*/
            }
        }else{
            $list = array();
        }

        return array(
            'list' => $list,
            'page' => $page,
            'limit' => $limit,
            'count' => $count,
        );
    }

    /**
     * 订单详情
     */
    public function detail(){
        $res = $this->checkData(
            ["order_id"],
            ["订单ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $order = db('order')->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        $order['address'] = json_decode($order['address']);
        $order['remarks'] = htmlspecialchars_decode($order['remarks']);
        $order['express_type'] = htmlspecialchars_decode($order['express_type']);
        $order['express_num'] = htmlspecialchars_decode($order['express_num']);
        $order['refund'] = null;
        if($order['refund_id'] > 0){
            $order['refund'] = db('refund')->where(['refund_id' => $order['refund_id'],'order_id' => $order['order_id']])->find();
            $order['refund']['images'] = json_decode($order['refund']['images']);
            foreach($order['refund']['images'] as &$fg){
                $fg = __ROOT__ . '/static/uploads/'.str_replace('\\',"/",$fg);
            }
            if(!empty($order['refund']['reason'])){
                $order['refund']['reason'] = htmlspecialchars_decode($order['refund']['reason']);
            }

        }
        $order['goods'] = db('order_product')->where(['order_id' => $order['order_id']])->select();
        foreach($order['goods'] as &$og){
            if(!empty($og['product_img'])){
                $og['product_img'] = __ROOT__ . '/static/uploads'.str_replace('\\',"/",$og['product_img']);
            }
        }
        $order['create_time'] = date('Y-m-d',$order['create_time']);
        return $order;
    }

    /**
     * 支付完成
     */
    public function afterPay($pay_log,$pay_type){
        Db::startTrans();
        try{

            db('pay_log')->where(['pay_sn' => $pay_log['pay_sn']])->update(['status' => 1,'pay_type' => $pay_type,'pay_time' => TIMESTAMP]);

            db('order')->where(['order_id' => $pay_log['record_id']])->update(['pay_time' => TIMESTAMP,'order_state' => ORDER_STATUS_PAID]);

            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            Log::WARN('支付单号：'.$pay_log['pay_sn'].',更新数据失败,错误信息:'.$e->getMessage(),'error');
            return false;
        }
        return true;
    }


    /**
     * 取消订单
     */
    public function cancel(){
        $res = $this->checkData(
            ["order_id"],
            ["订单ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $m_order = db('order');
        $order = $m_order->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        if($order['order_state'] != ORDER_STATUS_NOPAY) return array('message' => '该订单不支持此操作');
        $order_goods = db('order_product')->where(['order_id' => $order['order_id']])->select();

        Db::startTrans();
        try{

            $m_order->where(['order_id' => intval($this->requestData['order_id'])])->update(['order_state' => ORDER_STATUS_CLOSE]);

            //加回库存
            $m_goods_option_value = db('goods_option_value');
            foreach($order_goods as $g){
                $m_goods_option_value->where(['goodsid' => $g['product_id'],'spec_name' => $g['spec']])->setInc('stock',$g['count']);
            }


            if($order['voucher_id'] > 0){
                $m_voucher = db('myvoucher');
                $voucher = $m_voucher->where(['id' => $order['voucher_id']])->find();
                if($voucher && $voucher['end_time'] > TIMESTAMP){
                    $m_voucher->where(['id' => $order['voucher_id']])->update(['status' => 0]);
                }
            }

            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            return array('message' => '系统错误');
        }
        return array();
    }


    /**
     * 确认收货
     */
    public function receive(){
        $res = $this->checkData(
            ["order_id"],
            ["订单ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $m_order = db('order');
        $order = $m_order->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        if(!in_array($order['order_state'],[ORDER_STATUS_PAID,ORDER_STATUS_SENT])) return array('message' => '该订单不支持此操作');

        Db::startTrans();
        try{
            $m_order->where(['order_id' => intval($this->requestData['order_id'])])->update(['order_state' => ORDER_STATUS_SUCCESS]);
            //增加销量
            $m_order_product = db('order_product');
            $m_goods = db('goods');
            $order_goods = $m_order_product->where(['order_id' => $order['order_id']])->select();
            foreach($order_goods as $og){
                $m_goods->where(['id' => $og['product_id']])->setInc('sales_num',$og['count']);
            }
            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            return array('message' => $e->getMessage());
        }

        return array();

    }


    /**
     * 退款
     */
    public function refund()
    {
        $res = $this->checkData(
            ["order_id","reason","des","address_id"],
            ["订单ID不能为空","退款原因不能为空","说明不能为空","地址ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $m_order = db('order');
        $order = $m_order->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        //if($order['refund_id'] > 0) return array('message' => '不能重复退款');
        //查询退款
        $where['order_id'] = intval($this->requestData['order_id']);
        $refund_result = db('refund')->where($where)->order('refund_id asc')->select();
        $order_product_result = db('order_product')->where($where)->select();

        $refund_id_array = array_column($refund_result,'refund_id');       
        $refund_goods_id = array_column($refund_result,'goods_id');

        $order_product_id = array_column($order_product_result,'product_id');
        $order_product_price = array_column($order_product_result,'product_price');
        $order_product_count = array_column($order_product_result,'count');

        $refund_combine = array_combine($refund_id_array,$refund_goods_id);
        $product_combine = array_combine($order_product_id,$order_product_price);
        $product_combine_count = array_combine($order_product_id,$order_product_count);

        if(empty($this->requestData['goods_id'])){
            //单个订单退款
            $goods_id = 0;
            $goods_refund_price = 0;

            //计算出单个商品退款的款额
            foreach($refund_result as $v){
                $goods_refund_price += $v['money'];
            }

            //减去服务费以及之前退款的商品费
            $refund_price = $order['paid_price'] - $order['postage'] - $goods_refund_price;
        }else{
            //单个商品退款
            $goods_id = $this->requestData['goods_id'];

            if(in_array($goods_id, $refund_combine))return array('message'=>'不能重复退款');
            if(!isset($product_combine[$goods_id]))return array('message'=>'该订单没有购买该商品');
            if(!isset($product_combine_count[$goods_id]))return array('message'=>'该订单没有购买该商品');
            $refund_price = $product_combine[$goods_id] * $product_combine_count[$goods_id];
        }

        if($refund_price == 0)return array('message'=>'该订单申请过退款');
        if(in_array(0, $refund_combine))return array('message'=>'不能重复退款');

        switch ($order['order_state']){
            case ORDER_STATUS_PAID:

                break;
            case ORDER_STATUS_SENT:
                return array('message' => '需要先确认收货后才能发起退款');
                break;
            case ORDER_STATUS_SUCCESS:

                break;
            default:
                return array('message' => '该订单不支持此操作');
        }

        $address = db('user_address')->field('name,mobile,province,city,country,detail')
            ->where([
                'address_id' => intval($this->requestData['address_id']),
                'user_id' => $this->user['uid']
            ])->find();
        if(!$address) return array('message' => '找不到收货地址');
        Db::startTrans();
        try{
            $data = array(
                'order_id' => $order['order_id'],
                'create_time' => TIMESTAMP,
                'money' => $refund_price,
                'reason' => htmlspecialchars($this->requestData['reason']),
                "des" => htmlspecialchars($this->requestData['des']),
                'refund_sn' => 'R'.$this->generateOrderNo(),
                'address' => json_encode($address),
                'goods_id' => $goods_id
            );

            $refund_id = db('refund')->insertGetId($data);
            $refund_id_array[]=$refund_id;

            $refund_id_string = implode(',', $refund_id_array);

            $m_order->where(['order_id' => intval($this->requestData['order_id'])])->update(['refund_id' => $refund_id_string]);

            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            return array('message' => $e->getMessage());
        }
        return array();

    }


    /**
     * 快递信息
     */
    public function express(){
        $res = $this->checkData(
            ["order_id"],
            ["订单ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $order = db('order')->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        if($order['order_state'] != ORDER_STATUS_SENT) return array('message' => '该订单不支持此操作');
        return array(
            'express_name' => $order['express_type'],
            'express_num' => $order['express_num'],
        );

    }


    //再次订单购买
    public function order_pay_sn(){
        $res = $this->checkData(
            ["order_id"],
            ["订单ID不能为空"]
        );
        if(array_key_exists('message',$res)) return $res;
        $order = db('order')->where(['order_id' => intval($this->requestData['order_id'])])->find();
        if(!$order) return array('message' => '找不到订单');
        if($order['user_id'] != $this->user['uid']) return array('message' => '无权操作');
        $data = [];
        $pay_sn = 'P'.$this->generateOrderNo();
        db('pay_log')->where(['record_id'=>$this->requestData['order_id']])->update(['pay_sn'=>$pay_sn]);

        $result = db('pay_log')->where(['record_id'=>$this->requestData['order_id']])->find();
        $data['pay_sn'] = $result['pay_sn'];
        $data['money'] = $result['money'];
        $data['create_time'] = $result['create_time'];
        return $data;
    }





}